<?php
/**
 * Product's price management class
 *
 * @access		public
 * @author		Svilen Spasov <svilen@svilen.com>
 * @package		AMBilling System
 *
 * @since			28-02-2006
 * @version		1.9
 */
class Price {
	/**
	 * Product Id
	 * @access   public
	 * @var 		 int
	 */
	var $productId;
	
	/**
	 * Db Object
	 * @access   private
	 * @var 		 object
	 */
	var $anydb;
	
	/**
	 * Price data array
	 * @access   private
	 * @var 		 array
	 */
	var $prices;
	
	/**
	 * error handler
	 * @access   private
	 * @var 		 object
	 */
	var $error;
	
	/**
	 * price type
	 * @access   private
	 * @var 		 string
	 */
	var $priceType;
	
	/**
	 * price currency
	 * @access   public
	 * @var 		 string
	 */
	var $currency;
	
	/**
	 * price currency object
	 * @access   private
	 * @var 		 string
	 */
	var $currencyObject;
	
	/**
	 * price period
	 * @access   public
	 * @var 		 string
	 */
	var $period;
	
	/**
	 * default period for which every product MUST have a price
	 * @access   public
	 * @var 		 int
	 */
	var $defaultPeriod = 12;
	
	/**
	 * VAT value; for now it is set to 0 since we do not have VAT
	 * @access   public
	 * @var 		 int
	 */
	var $vat = 0;
	
	/**
	 * product id field
	 * @access   private
	 * @var 		 int
	 */
	var $productIdField = 'product_id';
	
	/**
	 * Constructor defines basic objects
	 *
	 * @access   public
	 * @author   Svilen Spasov <svilen@svilen.com>
	 *
	 * @param 	 int			$productId			Product Id
	 * @param 	 object		$dbHandler		AnyDb object
	 *
	 * @see 		 Error::addError()
	 *
	 * @since    28-02-2006
	 * @version  1.0
	 */
	function Price ($dbHandler, $error, $productId, $priceType, $period = 12, $currency = 'USD', $productIdField = 'product_id') {
		// Initialize error handler
		$this->error = $error;
		
		if (empty($dbHandler)) {
			$this->error->addError(1, 'Price requires anydb handler to be passed', FATAL_ERROR, true);
		}
		
		$this->anydb = $dbHandler;
		$this->productId = $productId;
		$this->productIdField = $productIdField;
		$this->priceType = $priceType;
		$this->currency = $currency;
		$this->period = $period;
		$this->currencyObject = new Currencies($dbHandler, $this->currency);
		
		$this->getPrices();
	}
	
	/**
	 * Sets a price by currency, period, type
	 *
	 * @author   Svilen Spasov <svilen@svilen.com>
	 *
	 * @param 	 float		$price				Price to be set
	 * @param 	 string		$priceType		price type
	 * @param 	 string		$currency			currency
	 * @param 	 int			$period				period
	 *
	 * @return   bool			TRUE/FALSE
	 *
	 * @see 		 Error::addError()
	 * @see 		 AnyDB::query()
	 * @see 		 AnyDB::numRows()
	 *
	 * @since    28-02-2006
	 * @version  1.0
	 */
	function set ($price, $period = NULL, $currency = NULL) {
		$price = $this->anydb->escapeStr($price);
		$productId = (int) $this->productId;
		$currency = !empty($currency) ? $this->anydb->escapeStr(strtoupper($currency)) : $this->anydb->escapeStr(strtoupper($this->currency));
		$period = !empty($period) ? (int) $period : (int) $this->period;
		
		$priceId = $this->anydb->escapeStr($this->prices[$currency][$period]['price_id']);
		
		if (empty($currency) || empty($period) || empty($this->priceType)) {
			$this->error->addError(20, 'Wrong params for set() method in Price class');
			return FALSE;
		}
		
		$query = <<<echo
SELECT price_id as price_id FROM prices WHERE price_id = $priceId
echo;
		$this->anydb->query($query);
		
		// check for error
		if (!empty($this->anydb->error)) {
			$this->error->addError(21, $this->anydb->error, FATAL_ERROR, TRUE);
			return FALSE;
		}
		
		if ($this->anydb->numRows()) {
			$query = <<<echo
UPDATE prices SET $this->priceType = $price, date = NOW() WHERE price_id = $priceId
echo;
			$this->anydb->query($query);
		}
		else {
			$query = <<<echo
INSERT INTO prices ($this->productIdField, currency, period, $this->priceType, date) VALUES ($productId, $currency, $period, $price, NOW())
echo;
			$this->anydb->query($query);
		}
		
		// check for error
		if (!empty($this->anydb->error)) {
			$this->error->addError(21, $this->anydb->error, FATAL_ERROR, TRUE);
			return FALSE;
		}
		
		// update internal data array
		$this->prices[$currency][$period][$this->priceType] = $price;
		
		return TRUE;
	}
	
	/**
	 * Get price by period, currency (auto calculates currency if not available by exchange rate in the "currency" table)
	 *
	 * @access   public
	 * @author   Svilen Spasov <svilen@svilen.com>
	 *
	 * @param 	 string		$currency			currency
	 * @param 	 int			$period				period
	 *
	 * @return 	 float		price
	 *
	 * @see 		 Error::addError()
	 *
	 * @since    28-02-2006
	 * @version  1.0
	 */
	function get ($period = NULL, $currency = NULL) {
		$price = '';
		$period = !empty($period) ? (int) $period : (int) $this->period;
		$currency = !empty($currency) ? strtoupper($currency) : strtoupper($this->currency);
		
		if (empty($currency) || empty($period) || empty($this->priceType)) {
			$this->error->addError(20, 'Wrong params for get() method in Price class');
			return FALSE;
		}
		
		if (empty($this->prices[$currency])) {
			// calculate required price since it is in other than products available currencies
			$price = $this->prices[$this->currency][$period][$this->priceType] * $this->currencyObject->getExchangeRateTo($currency);
		}
		else {
			// get required price
			$price = $this->prices[$currency][$period][$this->priceType];
		}
		
		// custom calculation of price
		if (empty($price)) {
			if (empty($this->prices[$currency])) {
				$price = $this->prices[$this->currency][$this->defaultPeriod][$this->priceType] * $this->currencyObject->getExchangeRateTo($currency);
			}
			else {
				$price = $this->prices[$currency][$this->defaultPeriod][$this->priceType];
			}
			
			$price = $price / $this->defaultPeriod;
			$price = $price * $period;
		}
		
		return !empty($price) ? $price : NULL;
	}
	
	/**
	 * Internal method for setting the data array
	 *
	 * @access   public
	 * @author   Svilen Spasov <svilen@svilen.com>
	 *
	 * @see 		 Error::addError()
	 * @see 		 AnyDB::query()
	 * @see 		 AnyDB::getNext()
	 *
	 * @since    28-02-2006
	 * @version  1.0
	 */
	function getPrices () {
		$productId = (int) $this->productId;
		$currency = '';
		
		$query = <<<echo
SELECT price_id as price_id, $this->productIdField as product_id, currency as currency, period as period, min_price as min_price, max_price as max_price, wholesale as wholesale, price as price, date as date FROM prices WHERE $this->productIdField = $productId AND state = 1
echo;
		$this->anydb->query($query);
		// check for error
		if (!empty($this->anydb->error)) {
			$this->error->addError(21, $this->anydb->error, FATAL_ERROR, TRUE);
			return FALSE;
		}
		// fill object's data array
		while ($row = $this->anydb->getNext()) {
			$currency = strtoupper($row['currency']);
			$this->prices[$currency][$row['period']] = $row;
		}
	}
	
	/**
	 * Get VAT by currency, period
	 *
	 * @access   public
	 * @author   Svilen Spasov <svilen@svilen.com>
	 *
	 * @param 	 string		$currency			currency
	 * @param 	 int			$period				period
	 *
	 * @return 	 float		price					VAT
	 *
	 * @see 		 Error::addError()
	 *
	 * @since    10-03-2006
	 * @version  1.0
	 */
	function getVat ($period = NULL, $currency = NULL) {
		$price = '';
		$period = !empty($period) ? (int) $period : (int) $this->period;
		$currency = !empty($currency) ? strtoupper($currency) : strtoupper($this->currency);
		
		if (empty($currency) || empty($period) || empty($this->priceType)) {
			$this->error->addError(20, 'Wrong params for getVat() method in Price class', FATAL_ERROR, TRUE);
			return FALSE;
		}
		
		// get vat
		$price = $this->get($period, $currency) * $this->vat;
		
		// return result
		return !empty($price) ? $price : NULL;
	}
	
	/**
	 * Get price by currency, period, type
	 *
	 * @access   public
	 * @author   Svilen Spasov <svilen@svilen.com>
	 *
	 * @param 	 string		$currency			currency
	 * @param 	 int			$period				period
	 *
	 * @return 	 float		price					Total price include VAT
	 *
	 * @see 		 Error::addError()
	 *
	 * @since    10-03-2006
	 * @version  1.0
	 */
	function getTotal ($period = NULL, $currency = NULL) {
		$price = '';
		$period = !empty($period) ? (int) $period : (int) $this->period;
		$currency = !empty($currency) ? strtoupper($currency) : strtoupper($this->currency);
		
		if (empty($currency) || empty($period) || empty($this->priceType)) {
			$this->error->addError(20, 'Wrong params for getTotal() method in Price class', FATAL_ERROR, TRUE);
			return FALSE;
		}
		
		// get total price
		$price = $this->get($period, $currency) + $this->getVat($period, $currency);
		
		// return result
		return !empty($price) ? $price : NULL;
	}
}
?>